import logging

from aiogram import Bot, types
from aiogram_dialog import Dialog, DialogManager, Window
from aiogram_dialog.widgets.input import TextInput
from aiogram_dialog.widgets.kbd import Button, Cancel, Url
from aiogram_dialog.widgets.text import Format
from fluentogram import TranslatorRunner
from sqlalchemy.ext.asyncio import AsyncSession

from src.config import Settings
from src.infrastructure.db.services.payments import create_payment, update_payment
from src.infrastructure.db.services.stats import update_stats
from src.infrastructure.db.services.users import increase_user_balance
from src.infrastructure.payment_client import PayPalychClient
from src.infrastructure.utils.helpers import get_rate_usd
from src.presentation.tg_bot.dialogs.widgets import LocaleText
from src.presentation.tg_bot.services.tg_helpers import broadcast
from src.presentation.tg_bot.states import PaymentSG

logger = logging.getLogger(__name__)


async def check_payment(call: types.CallbackQuery, _, manager: DialogManager):
    locale: TranslatorRunner = manager.middleware_data.get("locale")
    db_session: AsyncSession = manager.middleware_data.get("db_session")
    payment_client: PayPalychClient = manager.middleware_data.get("payment_client")
    bot: Bot = manager.middleware_data.get("bot")
    config: Settings = manager.middleware_data.get("config")

    bill_id = manager.dialog_data.get("bill_id")
    payment_id = manager.dialog_data.get("payment_id")
    user_id: int = call.from_user.id
    usd_summ: float = manager.dialog_data.get("usd_summ")

    try:
        bill = await payment_client.get_bill(bill_id)

        bill_status = bill.get("status")

        if not bill_status:
            await call.answer(locale.get("error-msg"))

        if bill_status == "NEW":
            await call.answer(locale.get("payment-waiting"))

        elif bill_status == "SUCCESS":
            await call.answer(locale.get("payment-successful"))
            await update_payment(db_session, payment_id, status="paid")
            await increase_user_balance(db_session, user_id, usd_summ)  # Пополняем баланс юзера на сумму в $
            await update_stats(db_session, payments_payed=1)
            await manager.done()

        elif bill_status == "FAIL":
            await call.message.answer(locale.get("payment-fail", payment_id=payment_id))
            await update_payment(db_session, payment_id, status="payment_failed")
            await manager.done()

    except Exception as e:
        await call.answer(locale.get("error-msg"))
        logger.exception(e)
        await broadcast(
            bot,
            [config.tg_bot.developer_id],
            f"Ошибка во время проверки оплаты: {str(e)}",
        )


async def set_payment_amount(message: types.Message, _, manager: DialogManager, selected_amount: str):
    locale: TranslatorRunner = manager.middleware_data.get("locale")
    db_session = manager.middleware_data.get("db_session")
    payment_client: PayPalychClient = manager.middleware_data.get("payment_client")
    bot: Bot = manager.middleware_data.get("bot")
    config: Settings = manager.middleware_data.get("config")
    user_id: int = message.from_user.id
    usd_rate: float = manager.dialog_data.get("usd_rate")

    try:
        summ: float = float(selected_amount)
        payment_summ = round(summ * usd_rate, 2)  # Конвертируем доллары в рубли и округляем

        payment = await create_payment(db_session, payment_summ, user_id)
        bill = await payment_client.create_bill(amount=payment_summ, order_id=payment.id)

        if not bill:
            await message.answer(locale.get("error-msg"))
            return

        payment.bill_id = bill.get("bill_id")

        logger.info(f"Создан новый счет {bill}")
        logger.info(f"Добавлена новая оплата №{payment.id} на сумму {payment.summ} руб.s")

        manager.dialog_data["usd_summ"] = summ
        manager.dialog_data["payment_summ"] = payment_summ
        manager.dialog_data["payment_id"] = payment.id
        manager.dialog_data["bill_id"] = bill.get("bill_id")
        manager.dialog_data["bill_link"] = bill.get("link_page_url")
        await db_session.commit()

        await manager.switch_to(PaymentSG.create_payment)
    except ValueError:
        await message.answer(locale.get("summ-wrong-format"))
    except Exception as e:
        logger.exception(e)
        await message.answer(locale.get("error-msg"))
        await broadcast(
            bot,
            [config.tg_bot.developer_id],
            f"Ошибка во время создания счета для оплаты: {str(e)}",
        )


async def get_usd_rate(dialog_manager: DialogManager, **kwargs):
    usd_rate = await get_rate_usd()
    dialog_manager.dialog_data["usd_rate"] = usd_rate

    return {"usd_rate": usd_rate}
